// Copyright Epic Games, Inc. All Rights Reserved.

#include "SmartMenuHandle.h"



USmartMenu* USmartMenuHandle::LevelToolbarMenu;
USmartMenu* USmartMenuHandle::AssetMenu;
USmartMenu* USmartMenuHandle::AssetSmartMenu;
USmartMenu* USmartMenuHandle::ActorMenu;
USmartMenu* USmartMenuHandle::MainMenu;
USmartMenu* USmartMenuHandle::ActorSmartMenu;
USmartMenu* USmartMenuHandle::SequencerToolbarMenu;
USmartMenuHandle* USmartMenuHandle::SmartMenuHandleInstance;

USmartMenu* USmartMenuHandle::GetMainMenu()
{
	if (MainMenu == nullptr)
	{
		MainMenu = NewObject<USmartMenu>();
		MainMenu->AddToRoot();
	}
	return MainMenu;
}


USmartMenu* USmartMenuHandle::GetLevelToolbarMenu()
{
	if (LevelToolbarMenu == nullptr)
	{
		LevelToolbarMenu = NewObject<USmartMenu>();
		LevelToolbarMenu->AddToRoot();
	}
	return LevelToolbarMenu;
}

USmartMenu* USmartMenuHandle::GetAssetMenu()
{
	if (AssetMenu == nullptr)
	{
		AssetMenu = NewObject<USmartMenu>();
		AssetMenu->AddToRoot();
	}
	return AssetMenu;
}

USmartMenu* USmartMenuHandle::GetAssetSmartMenu()
{
	if (AssetSmartMenu == nullptr)
	{
		AssetSmartMenu = NewObject<USmartMenu>();
		AssetSmartMenu->AddToRoot();
	}
	return AssetSmartMenu;
}

USmartMenu* USmartMenuHandle::GetActorMenu()
{
	if (ActorMenu == nullptr)
	{
		ActorMenu = NewObject<USmartMenu>();
		ActorMenu->AddToRoot();
	}
	return ActorMenu;
}

USmartMenu* USmartMenuHandle::GetActorSmartMenu()
{
	if (ActorSmartMenu == nullptr)
	{
		ActorSmartMenu = NewObject<USmartMenu>();
		ActorSmartMenu->AddToRoot();
	}
	return ActorSmartMenu;
}

USmartMenu* USmartMenuHandle::GetSequencerToolbarMenu()
{
	if (SequencerToolbarMenu == nullptr)
	{
		SequencerToolbarMenu = NewObject<USmartMenu>();
		SequencerToolbarMenu->AddToRoot();
	}
	return SequencerToolbarMenu;
}

USmartMenuHandle::USmartMenuHandle(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

void USmartMenuHandle::InitMenuEnv()
{
	LevelToolbarMenu = GetLevelToolbarMenu();
	AssetMenu = GetAssetMenu();
	AssetSmartMenu = GetAssetSmartMenu();
	ActorMenu = GetActorMenu();
	ActorSmartMenu = GetActorSmartMenu();
	SequencerToolbarMenu = GetSequencerToolbarMenu();

	TArray<USmartMenuItemBase*> EnvToolbarMenuItems = GetMenuItemsFromEnv(FString("UNREAL_LEVEL_TOOLBAR_MENU_CONFIGS"));
	TArray<USmartMenuItemBase*> EnvAssetMenuItems = GetMenuItemsFromEnv(FString("UNREAL_ASSET_MENU_CONFIGS"));
	TArray<USmartMenuItemBase*> EnvAssetSmartMenuItems =
		GetMenuItemsFromEnv(FString("UNREAL_ASSET_SMART_MENU_CONFIGS"));
	TArray<USmartMenuItemBase*> EnvActorMenuItems = GetMenuItemsFromEnv(FString("UNREAL_ACTOR_MENU_CONFIGS"));
	TArray<USmartMenuItemBase*> EnvActorSmartMenuItems =
		GetMenuItemsFromEnv(FString("UNREAL_ACTOR_SMART_MENU_CONFIGS"));
	TArray<USmartMenuItemBase*> EnvSequencerMenuItems = GetMenuItemsFromEnv(
		FString("UNREAL_SEQUENCER_TOOLBAR_MENU_CONFIGS"));
	if (EnvToolbarMenuItems.Num() != 0)
	{
		LevelToolbarMenu->Items.Append(EnvToolbarMenuItems);
	}

	if (EnvAssetMenuItems.Num() != 0)
	{
		AssetMenu->Items.Append(EnvAssetMenuItems);
	}
	if (EnvAssetSmartMenuItems.Num() != 0)
	{
		AssetSmartMenu->Items.Append(EnvAssetSmartMenuItems);
	}

	if (EnvActorMenuItems.Num() != 0)
	{
		ActorMenu->Items.Append(EnvActorMenuItems);
	}
	if (EnvActorSmartMenuItems.Num() != 0)
	{
		ActorSmartMenu->Items.Append(EnvActorSmartMenuItems);
	}

	if (EnvSequencerMenuItems.Num() != 0)
	{
		SequencerToolbarMenu->Items.Append(EnvSequencerMenuItems);
	}
}

TArray<USmartMenuItemBase*> USmartMenuHandle::GetMenuItemsFromEnv(const FString& Env)
{
	TArray<USmartMenuItemBase*> Items;
	TArray<TSharedPtr<FJsonValue>> _MenuArray = GetMenuItemsDataFromEnv(Env);
	GetMenuItemsFromData(Items, _MenuArray);
	return Items;
}

void USmartMenuHandle::GetMenuItemsFromData(TArray<USmartMenuItemBase*>& Items,
                                            TArray<TSharedPtr<FJsonValue>> MenuJsonDatas)
{
	if (MenuJsonDatas.Num() != 0)
	{
		for (TSharedPtr<FJsonValue> Data : MenuJsonDatas)
		{
			TSharedPtr<FJsonObject> DataObject = Data->AsObject();
			TSharedPtr<FJsonValue> TypeValue = DataObject->TryGetField("type");
			if (!TypeValue.IsValid())
			{
				continue;
			}
			if (TypeValue->Type == EJson::String)
			{
				// GLog->Log(TypeValue->AsString());
				if (TypeValue->AsString().ToUpper() == FString("ACTION"))
				{
					FString InName;
					FString InCommand;
					FString InDescription;
					TSharedPtr<FJsonValue> nameJsonValue = DataObject->TryGetField("name");
					TSharedPtr<FJsonValue> commandJsonValue = DataObject->TryGetField("command");
					TSharedPtr<FJsonValue> descriptionJsonValue = DataObject->TryGetField("description");
					if (!commandJsonValue.IsValid())
					{
						continue;
					}
					USmartAction* _item = NewObject<USmartAction>();
					InCommand = commandJsonValue->AsString();
					_item->Command = InCommand;
					if (nameJsonValue.IsValid())
					{
						InName = nameJsonValue->AsString();
						_item->Name = InName;
					}
					if (descriptionJsonValue.IsValid())
					{
						InDescription = descriptionJsonValue->AsString();
						_item->Description = InDescription;
					}
					Items.Add(_item);
				}
				else if (TypeValue->AsString().ToLower() == FString("SEPARATOR"))
				{
					USmartSeparator* _item = NewObject<USmartSeparator>();
					Items.Add(_item);
				}
				else if (TypeValue->AsString().ToLower() == FString("MENU"))
				{
					FString InName;
					FString InDescription;
					TSharedPtr<FJsonValue> nameJsonValue = DataObject->TryGetField("name");
					TSharedPtr<FJsonValue> descriptionJsonValue = DataObject->TryGetField("description");
					USmartMenu* _item = NewObject<USmartMenu>();
					if (nameJsonValue.IsValid())
					{
						InName = nameJsonValue->AsString();
						_item->Name = InName;
					}
					if (descriptionJsonValue.IsValid())
					{
						InDescription = descriptionJsonValue->AsString();
						_item->Description = InDescription;
					}
					TSharedPtr<FJsonValue> OutputsValue = DataObject->TryGetField("outputs");
					if (OutputsValue.IsValid())
					{
						TArray<TSharedPtr<FJsonValue>> ChildrenDatas = OutputsValue->AsArray();
						GetMenuItemsFromData(_item->Items, ChildrenDatas);
					}
					Items.Add(_item);
				}
				else if (TypeValue->AsString().ToLower() == FString("BEGINSECTION"))
				{
					USmartBeginSection* _item = NewObject<USmartBeginSection>();
					Items.Add(_item);
				}
				else if (TypeValue->AsString().ToLower() == FString("ENDSECTION"))
				{
					USmartEndSection* _item = NewObject<USmartEndSection>();
					Items.Add(_item);
				}
			}
		}
	}
}

TArray<TSharedPtr<FJsonValue>> USmartMenuHandle::GetMenuItemsDataFromEnv(const FString& Env)
{
	TArray<TSharedPtr<FJsonValue>> _MenuArray;

	TArray<FString> configFiles;
	//configFiles.Add(FPaths::ProjectConfigDir() + "menu.json");
	{
		FString confgi_str = FPlatformMisc::GetEnvironmentVariable(*Env);
		if (!confgi_str.IsEmpty())
		{
			USmartCore::StringSplit(confgi_str, ";", configFiles);
		}
	}
	for (FString _file : configFiles)
	{
		if (FPaths::FileExists(_file))
		{
			FString JsonString; //Json converted to FString
			FFileHelper::LoadFileToString(JsonString, *_file);
			TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(JsonString);
			TArray<TSharedPtr<FJsonValue>> jsonArray;
			if (FJsonSerializer::Deserialize(JsonReader, jsonArray))
			{
				// GLog->Log(FString::FromInt(jsonArray.Num()));

				_MenuArray.Append(jsonArray);
			}
		}
	}

	return _MenuArray;
}
